﻿using System;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using System.Linq;

using BizElements.Core;
using BizElements.TemplateEngine;
using BizElements.Generator.Oracle;
using BizElements.Generator.SqlServer;
using BizElements.Generator.SqlServerCe;
using BizElements.Generator.PostgreSql;
using BizElements.Generator.MySql;

namespace BizElements.Generator
{
    public partial class DbProjectCtl : UserControl, IProjectUserControl
    {
        VariableValueBus variableBus;

        public DbProjectCtl()
        {
            InitializeComponent();
            // Generator properties are set/pulled on demand, ie. when generator user control requests it.
            this.uiGenerator.BuildGeneratorProperties = this.CreateGeneratorProperties;
            this.uiGenerator.BuildGenerator = this.CreateGenerator;
            this.variableBus = new VariableValueBus(this.GetVariableValue, GetSuppressedVariables());
            this.uiCodeOptions.VariableBus = this.variableBus;
        }        

        private void DbProjectCtl_Load(object sender, EventArgs e)
        {
            this.uiMetaSource.Connected += new EventHandler(uiMetaSource_Connected);
            this.uiMetaSource.Disconnected += new EventHandler(uiMetaSource_Disconnected);                        
        }

        #region Metadata source - connected/disconnected events.

        private void uiMetaSource_Connected(object sender, EventArgs e)
        {
            this.uiMainTab.SelectedTab = this.uiCodeOptionsPage;
            this.uiTableList.MetaDataSource = this.uiMetaSource.MetaDataSource;
            this.uiTableList.Enabled = true;
            this.uiSpList.MetaDataSource = this.uiMetaSource.MetaDataSource;
            this.uiSpList.Enabled = true;
            this.uiGenerator.Enabled = true;

            this.variableBus.PushVariableValue("ConnectionString", this.uiMetaSource.MetaDataSource.ConnectionString);
        }

        private void uiMetaSource_Disconnected(object sender, EventArgs e)
        {
            this.uiTableList.Enabled = false;
            this.uiTableList.MetaDataSource = null;
            this.uiSpList.Enabled = false;
            this.uiSpList.MetaDataSource = null;
            this.uiGenerator.Enabled = false;
        }

        #endregion

        #region CreateGenerator and CreateGeneratorProperties - on generator request.

        private DbProjectGeneratorProperties CreateGeneratorProperties()
        {
            if (this.WriteProjectSettingsDemanded != null)
                WriteProjectSettingsDemanded(this, new EventArgs());

            DbProjectGeneratorProperties properties = new DbProjectGeneratorProperties();           

            // Generator properties are set/pulled on demand, ie. when generator user control requests it.
            properties.MetaDataSource = this.uiMetaSource.MetaDataSource;
            properties.SelectedItems = this.uiTableList.SelectedTableAndViewNames;
            properties.SelectedViews = this.uiTableList.GetSelectedViewNames();
            properties.ExcludedColumnsRegex = this.uiTableList.ExcludedColumnsRegex;
            properties.SelectedProcedures = this.uiSpList.SelectedProcedures;
            properties.ItemTemplates = this.uiCodeOptions.TableItemTemplates;
            properties.SpAndCatalogTemplate = this.uiCodeOptions.SpAndCatalogTemplate;
            properties.OutputFolder = this.uiGenerator.OutputDirectory;
            var defaultTypeMapper = DbGeneratorComponentFactory.GetTypeMappers(properties.MetaDataSource.DBMS).ElementAt(0);
            properties.TypeMapper = defaultTypeMapper;
            properties.AllComponentVariables = this.uiTableList.GetAllComponentVariables();

            return properties;
        }

        private ICodeGenerator CreateGenerator(ICodeGeneratorProperties properties)
        {
            return new DbProjectGenerator((DbProjectGeneratorProperties)properties);
        }

        #endregion

        #region Project settings.

        public void ReadProjectSettings(BizElementsSettings projectSettings)
        {
            this.uiMainTab.SelectedTab = this.uiSourcePage;
            this.uiMetaSource.ReadSettings(projectSettings);
            this.uiTableList.ReadSettings(projectSettings);
            this.uiSpList.ReadSettings(projectSettings);
            this.uiCodeOptions.ReadProjectSettings(projectSettings);
            this.uiGenerator.ReadSettings(projectSettings);
        }

        public void WriteProjectSettings(BizElementsSettings projectSettings)
        {
            this.uiMetaSource.WriteSettings(projectSettings);
            if (this.uiTableList.Enabled)
                this.uiTableList.WriteSettings(projectSettings);
            if (this.uiSpList.Enabled)
                this.uiSpList.WriteSettings(projectSettings);
            if (this.uiCodeOptions.Enabled)
                this.uiCodeOptions.WriteProjectSettings(projectSettings);
            if (this.uiGenerator.Enabled)
                this.uiGenerator.WriteSettings(projectSettings);
        }

        #endregion

        #region Variable bus.

        private static string[] GetSuppressedVariables()
        {
            string semicolDelimited = Properties.Settings.Default.DbProjectCtl_SuppressedVariables ?? "";
            List<string> varNames = new List<string>();
            foreach (string variable in semicolDelimited.Split(';'))
            {
                if (!string.IsNullOrEmpty(variable))
                    varNames.Add(variable);
            }

            return varNames.ToArray();
        }

        private string GetVariableValue(string variableName)
        {
            if ((variableName == "ConnectionString") && (this.uiMetaSource.MetaDataSource != null))
            {
                return this.uiMetaSource.MetaDataSource.ConnectionString;
            }
            else
            {
                return null;
            }
        }

        #endregion

        public event EventHandler WriteProjectSettingsDemanded;

        private void uiTableList_TemplatesRequested(object sender, EventArgs e)
        {
            this.uiTableList.SetTemplates(this.uiCodeOptions.TableItemTemplates);            
        }
    }
}
